package services

import (
	"fmt"
	"time"

	"github.com/google/uuid"

	"b2c-delivery-optimization/internal/algorithm"
	"b2c-delivery-optimization/internal/model"

	"gorm.io/gorm"
)

// WaveService 波次管理服务
type WaveService struct {
	db        *gorm.DB
	strategy  *algorithm.WaveAllocationStrategy
	predictor *algorithm.WavePredictor
}

// generateID 生成唯一ID
func generateID() string {
	return uuid.New().String()
}

// NewWaveService 创建波次管理服务实例
func NewWaveService(db *gorm.DB) *WaveService {
	return &WaveService{
		db:        db,
		strategy:  algorithm.NewWaveAllocationStrategy(50), // 默认每波次最多50个订单
		predictor: algorithm.NewWavePredictor(db),
	}
}

// CreateWave 创建新波次
func (s *WaveService) CreateWave(wave *model.Wave) error {
	wave.Status = model.WaveStatusCreated
	wave.StartTime = time.Now()
	wave.EndTime = time.Now().Add(24 * time.Hour) // 默认24小时后结束
	return s.db.Create(wave).Error
}

// GetWave 获取波次详情
func (s *WaveService) GetWave(id string) (*model.Wave, error) {
	var wave model.Wave
	if err := s.db.First(&wave, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &wave, nil
}

// ListWaves 列出波次
func (s *WaveService) ListWaves(query *model.WaveQuery) ([]model.Wave, int64, error) {
	var waves []model.Wave
	var total int64
	db := s.db.Model(&model.Wave{})

	if query.Status != 0 {
		db = db.Where("status = ?", query.Status)
	}
	if query.DeliveryStationID != "" {
		db = db.Where("delivery_station_id = ?", query.DeliveryStationID)
	}
	if !query.StartTime.IsZero() {
		db = db.Where("start_time >= ?", query.StartTime)
	}
	if !query.EndTime.IsZero() {
		db = db.Where("end_time <= ?", query.EndTime)
	}
	if query.Priority > 0 {
		db = db.Where("priority = ?", query.Priority)
	}

	// 如果指定了创建时间范围，则按创建时间过滤
	if !query.CreatedAfter.IsZero() {
		db = db.Where("created_at >= ?", query.CreatedAfter)
	}
	if !query.CreatedBefore.IsZero() {
		db = db.Where("created_at < ?", query.CreatedBefore)
	}

	// 先获取总数
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 如果没有数据，直接返回
	if total == 0 {
		return []model.Wave{}, 0, nil
	}

	// 获取分页数据
	offset := (query.Page - 1) * query.PageSize
	if err := db.Offset(offset).Limit(query.PageSize).Find(&waves).Error; err != nil {
		return nil, 0, err
	}

	return waves, total, nil
}

// UpdateWaveStatus 更新波次状态
func (s *WaveService) UpdateWaveStatus(id string, status model.WaveStatus) error {
	updates := map[string]interface{}{
		"status": status,
	}

	switch status {
	case model.WaveStatusReleased:
		updates["end_time"] = time.Now()
	}

	return s.db.Model(&model.Wave{}).Where("id = ?", id).Updates(updates).Error
}

// AddOrdersToWave 向波次添加订单
func (s *WaveService) AddOrdersToWave(waveID string, orderIDs []string) error {
	// 开启事务
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 创建波次订单关联
		for _, orderID := range orderIDs {
			waveOrder := &model.WaveOrder{
				ID:        generateID(),
				WaveID:    waveID,
				OrderID:   orderID,
				CreatedAt: time.Now(),
				UpdatedAt: time.Now(),
			}
			if err := tx.Create(waveOrder).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

// PredictReleaseTime 预测波次释放时间
func (s *WaveService) PredictReleaseTime(waveID string) (time.Time, error) {
	// 1. 获取当前波次信息
	wave, err := s.GetWave(waveID)
	if err != nil {
		return time.Time{}, err
	}

	// 2. 获取历史波次数据
	var historicalWaves []model.Wave
	if err := s.db.Where("status = ?", model.WaveStatusCompleted).
		Order("end_time desc").
		Limit(100).
		Find(&historicalWaves).Error; err != nil {
		return time.Time{}, err
	}

	// 3. 使用预测器预测释放时间
	predictedTime := s.predictor.PredictReleaseTime(wave, historicalWaves)

	return predictedTime, nil
}

// GetWaveOrders 获取波次中的订单
func (s *WaveService) GetWaveOrders(waveID string) ([]model.Order, error) {
	var orders []model.Order
	if err := s.db.Joins("JOIN wave_orders ON orders.id = wave_orders.order_id").
		Where("wave_orders.wave_id = ?", waveID).
		Preload("Items").
		Find(&orders).Error; err != nil {
		return nil, err
	}
	return orders, nil
}

func (s *WaveService) GetWave_Orders(waveID string) ([]model.WaveOrder, error) {
	var waveOrders []model.WaveOrder
	if err := s.db.Where("wave_id = ?", waveID).Find(&waveOrders).Error; err != nil {
		return nil, err
	}
	return waveOrders, nil
}

// ValidateWaveStatus 验证波次状态转换是否合法
func (s *WaveService) ValidateWaveStatus(currentStatus, newStatus model.WaveStatus) error {
	validTransitions := map[model.WaveStatus][]model.WaveStatus{
		model.WaveStatusPending: {
			model.WaveStatusCreated,
			model.WaveStatusCancelled,
		},
		model.WaveStatusCreated: {
			model.WaveStatusReleased,
			model.WaveStatusCancelled,
		},
		model.WaveStatusReleased: {
			model.WaveStatusPicking,
			model.WaveStatusCancelled,
		},
		model.WaveStatusPicking: {
			model.WaveStatusPacked,
			model.WaveStatusCancelled,
		},
		model.WaveStatusPacked: {
			model.WaveStatusLoading,
			model.WaveStatusCancelled,
		},
		model.WaveStatusLoading: {
			model.WaveStatusInTransit,
			model.WaveStatusCancelled,
		},
		model.WaveStatusInTransit: {
			model.WaveStatusDelivered,
			model.WaveStatusCancelled,
		},
		model.WaveStatusDelivered: {
			model.WaveStatusCompleted,
			model.WaveStatusCancelled,
		},
		model.WaveStatusCompleted: {
			// 已完成状态是终态，不能转换到其他状态
		},
		model.WaveStatusCancelled: {
			// 已取消状态是终态，不能转换到其他状态
		},
	}

	// 检查状态转换是否合法
	if validNextStates, exists := validTransitions[currentStatus]; exists {
		for _, validState := range validNextStates {
			if validState == newStatus {
				return nil
			}
		}
	}

	return fmt.Errorf("invalid status transition from %s to %s", currentStatus.String(), newStatus.String())
}

// AllocateOrdersToWaves 将订单分配到波次
func (s *WaveService) AllocateOrdersToWaves(orderIDs []string, maxOrdersPerWave int) error {
	// 获取订单信息
	var orders []model.Order
	if err := s.db.Where("id IN ?", orderIDs).Find(&orders).Error; err != nil {
		return fmt.Errorf("获取订单信息失败: %v", err)
	}
	// 设置策略参数
	s.strategy.MaxOrdersPerWave = maxOrdersPerWave
	// 使用策略分配订单到波次
	waveOrders, err := s.strategy.AllocateOrders(orders)
	if err != nil {
		return fmt.Errorf("分配订单到波次失败: %v", err)
	}
	// 开启事务
	tx := s.db.Begin()
	if tx.Error != nil {
		return fmt.Errorf("开启事务失败: %v", tx.Error)
	}
	// 保存波次和订单关联
	for _, wave := range waveOrders {
		// 创建新的波次实例
		now := time.Now()
		newWave := model.Wave{
			ID:                wave.ID,
			DeliveryStationID: wave.DeliveryStationID,
			Status:            model.WaveStatusCreated,
			StartTime:         now,
			EndTime:           now.Add(24 * time.Hour),
			CreatedAt:         now,
			UpdatedAt:         now,
		}

		// 创建波次
		if err := tx.Create(&newWave).Error; err != nil {
			tx.Rollback()
			return fmt.Errorf("创建波次失败: %v", err)
		}

		// 创建波次订单关联
		for _, order := range wave.Orders {
			waveOrder := &model.WaveOrder{
				ID:        generateID(),
				WaveID:    newWave.ID,
				OrderID:   order.ID,
				CreatedAt: now,
				UpdatedAt: now,
			}

			if err := tx.Create(waveOrder).Error; err != nil {
				tx.Rollback()
				return fmt.Errorf("创建波次订单关联失败: %v", err)
			}
		}
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return fmt.Errorf("提交事务失败: %v", err)
	}

	return nil
}
